package test;

import model.User;

import java.beans.Transient;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author zhaobaolin
 * @Date 2018/10/20
 */
public class Index {

    public static void main(String[] args) {
        
        //cla();
        //instance();
        //constructors();
        //field();
        //method();
        annotation();
        //invoke();
    }

    /**
     * 获取注解
     */
    private static void annotation()
    {
        Class cla = User.class;

        //获取类上的注解
        Annotation[] annotations = cla.getAnnotations();
        Arrays.stream(annotations).forEach(System.out::println);

        if(cla.isAnnotationPresent(Deprecated.class)){
            System.out.println(cla.getName()+"类含有Deprecated这个注解");
        }

        System.out.println("-----------------");

        //获取方法上的注解
        Method[] methods = cla.getDeclaredMethods();
        Arrays.stream(methods).filter((v)->v.getDeclaredAnnotations().length > 0).forEach((vvv)-> {
            Annotation[] a2 = vvv.getDeclaredAnnotations();
            System.out.print(vvv.toString() + ": ");
            Arrays.stream(a2).forEach(System.out::println);

            if(vvv.isAnnotationPresent(Transient.class)){
                System.out.println(vvv.getName()+"方法含有Transient这个注解");
            }
        });


    }

    /**
     * 获取class的三种方式
     */
    private static void cla()
    {
        //一般来说 这种方式几乎不会使用
        User user = new User(3L);
        Class c1 = user.getClass();
        System.out.println(c1);

        //在程序中反射某个类的信息时一般会使用这种方式
        Class c2 = User.class;
        System.out.println(c2);

        //当类路径从配置文件加载的时候会使用此种方式
        try{
            //无论何时使用这种方式必须提供一个错误处理器
            Class c3 = Class.forName("model.User");
            System.out.println(c3);
        }catch (ClassNotFoundException e){
            System.out.println("类不存在");
        }

    }

    /**
     * 根据class 获取对象实例
     */
    private static void instance()
    {
        Class c1 = User.class;
        try{
            Object object = c1.newInstance();//调用无参构造器  必须是显式构造器
            User user = (User) object;
            System.out.println(user.toString());
        }catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取构造函数
     */
    private static void constructors()
    {
        Class cla = User.class;
        Constructor[] constructors =  cla.getConstructors();//获取当前类的所有public构造函数
        //Constructor[] constructors =  cla.getDeclaredConstructors();//获取当前类的所有构造函数
        Arrays.stream(constructors).forEach((v)->{
            System.out.print(Modifier.toString(v.getModifiers()) + " " + v.getName() + "(");
            String string = Arrays.stream(v.getParameterTypes()).map(Class::getName).collect(Collectors.joining(","));
            System.out.println(string + ")");
        });
    }

    /**
     * 获取属性
     */
    private static void field()
    {
        Class cla = User.class;
        //Field[] fields = cla.getFields();//获取当前类包括超类的public属性
        Field[] fields = cla.getDeclaredFields();//获取当前类的所有属性 包括私有属性

        Arrays.stream(fields).forEach((v)->{
            String s = Modifier.toString(v.getModifiers()) + " " + v.getType().getName() + " " + v.getName();
            try{
                s += " = " + v.get(cla.newInstance());
            }catch (Exception e){

            }finally {
                System.out.println(s);
            }
        });
    }

    /**
     * 获取方法
     */
    private static void method()
    {
        Class cla = User.class;
        //Method[] methods = cla.getMethods();//获取当前对象包括超类对象包括Object对象的所有public方法
        Method[] methods = cla.getDeclaredMethods();//获取当前对象的所有方法 包括私有方法
        Arrays.stream(methods).forEach((v)->{
            //Type type = v.getGenericReturnType();//与getReturnType一样
            Type type = v.getReturnType();
            System.out.print(type.getTypeName()+" "+v.getName() + "(");

            Class[] params = v.getParameterTypes();
            String string = Arrays.stream(params).map(Class::getName).collect(Collectors.joining(","));
            System.out.println(string + ")");
        });
    }


    /**
     * 方法调用
     */
    private static void invoke()
    {
        Class cla = User.class;

        try{
            //调用某个类的某个方法
            User user = (User)cla.newInstance();

            Method method1 = cla.getMethod("setId", Long.class);
            method1.invoke(user,2L);

            Method method11 = cla.getMethod("getId");
            System.out.println(method11.invoke(user));


            //静态方法可传Null
            Method method2 = cla.getMethod("setSex", String.class);
            method2.invoke(null,"不男不女");

            Method method22 = cla.getMethod("getSex");
            System.out.println(method22.invoke(null));

        }catch (Exception e){
            e.printStackTrace();
        }
    }


}
